/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.model.core;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>Content Field Value (CFV) represents locale-dependent content of some {@link ContentField}.
 * It has a {@link ContentLocale} attached to it. That Content Locale is one
 * that corresponds to this Content Field Value.</p>
 * <p>Each Content Field Value belongs to some Content Field, which may have one
 * of three types: <b>LINE_TYPE</b>, <b>MULTILINE_TYPE</b> and <b>HTML_TYPE</b>.
 * If field has first of this types, CFV's value is stored as <b>simpleValue</b>,
 * else it's stored in <b>value</b>.</p>
 * <p><a href="ContentFieldValue.java.html"><i>View Source</i></a>
 * </p>
 * <p/>
 *
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.35 $ $Date: 2006/08/06 07:03:36 $
 * @see ContentLocale
 * @see ContentField
 * @hibernate.class table="`al_core_field_value`" lazy="false" dynamic-update="true" dynamic-insert="true"
 */
public class ContentFieldValue extends BaseObject {
	//~ Instance fields ========================================================

    /**
     * The ID of this CFV
     */
	protected Long id;
    /**
     * Content locale that corresponds to this value
     */
	protected ContentLocale contentLocale;
    /**
     * The value of this CFV if field type is not <code>LINE_TYPE</code>
     */
	protected byte[] value;
    /**
     * The value of this CFV if field type is <code>LINE_TYPE</code>
     */
	protected String simpleValue;
    /**
     * Content field to which this CFV belong
     */
	protected ContentField contentField;
    /**
     * Date and time of last update of this CFV
     */
	protected Date lastUpdatedDatetime = null;
    /**
     * Version of this field (used in optimistic locking)
     */
	protected Long version;

    /**
     * List of pages that are linked to this CFV
     */
	protected List linkedPages = new ArrayList();
    /**
     * List of content resources that are linked to this CFV
     */
	protected List linkedResources = new ArrayList();

	//~ Methods ================================================================
	/**
	 * Returns the id of this content field value
	 *
	 * @return the id
	 * @struts.form-field
	 * @hibernate.id column="`id`"
	 * generator-class="increment" unsaved-value="null"
	 */
	public Long getId() {
		return id;
	}

    /**
     * Sets the id of this content field value
     *
     * @param id new id
     */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Returns the content locale of this content field value
	 *
	 * @return the content locale
	 * @struts.form-field
	 * @hibernate.many-to-one column="`locale_identifier`" not-null="false" outer-join="false" lazy="false"
	 */
	public ContentLocale getContentLocale() {
		return contentLocale;
	}

    /**
     * Sets the content locale of this content field value
     *
     * @param contentLocale new content locale
     */
	public void setContentLocale(ContentLocale contentLocale) {
		this.contentLocale = contentLocale;
	}

	/**
	 * Returns the content for field with type <code>LINE_TYPE</code>
	 *
	 * @return value as of single-line
	 * @struts.form-field
	 * @hibernate.property
	 * @hibernate.column name="`simple_value`" not-null="false" length="252"
	 */
	public String getSimpleValue() {
		return simpleValue;
	}

    /**
     * Sets the content for field with type <code>LINE_TYPE</code>
     *
     * @param simpleValue the value to be set as a simple value
     */
	public void setSimpleValue(String simpleValue) {
		this.simpleValue = simpleValue;
	}

	/**
	 * Returns the field to which this CFV belong
	 *
	 * @return a field
	 * @hibernate.many-to-one column="`field_id`" not-null="false" outer-join="false" lazy="false"
	 */
	public ContentField getContentField() {
		return contentField;
	}

    /**
     * Sets the field to which this CFV belong
     *
     * @param contentField new master field
     */
	public void setContentField(ContentField contentField) {
		this.contentField = contentField;
	}

	/**
	 * Gets date/time when this content field value was created/last updated
	 *
	 * @return last updated datetime
	 * @hibernate.property
	 * @hibernate.column name="`last_updated`" not-null="true" unique="false"
	 */
	public Date getLastUpdatedDatetime() {
		return lastUpdatedDatetime;
	}

    /**
     * Sets date/time when this content field value was created/last updated
     *
     * @param lastUpdatedDatetime the date/time of creation/last update
     */
	public void setLastUpdatedDatetime(Date lastUpdatedDatetime) {
		this.lastUpdatedDatetime = lastUpdatedDatetime;
	}

	/**
     * Returns version of this content field value
     *
	 * @return the version
	 * @struts.form-field
	 * @hibernate.version column="`version`" type="long" unsaved-value="null"
	 */
	public Long getVersion() {
		return version;
	}

    /**
     * Sets version of this content field value
     *
     * @param version new version
     */
	public void setVersion(Long version) {
		this.version = version;
	}

	/**
	 * Gets list of pages this CFV is linked with
	 *
     * @return the list of linked pages
     * @hibernate.bag table="`al_core_field_value_page`" cascade="none" lazy="true" inverse="false" outer-join="false"
	 * @hibernate.collection-key column="`field_value_id`"
	 * @hibernate.collection-many-to-many class="com.blandware.atleap.model.core.Page" column="`page_id`" outer-join="false"
	 */
	public List getLinkedPages() {
		return linkedPages;
	}

    /**
     * Sets list of pages this CFV is linked with
     *
     * @param linkedPages the list of linked pages
     */
	public void setLinkedPages(List linkedPages) {
		this.linkedPages = linkedPages;
	}

    /**
     * Adds a connection between this CFV and a given page
     *
     * @param page the page to connect with
     */
    public void addLinkedPage(Page page) {
        if ( !page.getLinkedContentFieldValues().contains(this) ) {
            page.getLinkedContentFieldValues().add(this);
        }
        if ( !getLinkedPages().contains(page) ) {
            getLinkedPages().add(page);
        }
    }

    /**
     * Removes a connection between this CFV and a given page
     *
     * @param page the page
     */
    public void removeLinkedPage(Page page) {
        page.getLinkedContentFieldValues().remove(this);
        getLinkedPages().remove(page);
    }

	/**
	 * Gets list of content resources this CFV is linked with
	 *
     * @return the list of linked content resources
     * @hibernate.bag table="`al_core_field_value_resource`" cascade="none" lazy="true" inverse="false" outer-join="false"
	 * @hibernate.collection-key column="`field_value_id`"
	 * @hibernate.collection-many-to-many class="com.blandware.atleap.model.core.ContentResource" column="`resource_id`" outer-join="false"
	 */
	public List getLinkedResources() {
		return linkedResources;
	}

    /**
     * Sets list of content resources this CFV is linked with
     *
     * @param linkedResources the list of linked content resources
     */
	public void setLinkedResources(List linkedResources) {
		this.linkedResources = linkedResources;
	}

    /**
     * Adds a connection between this CFV and a given content resource
     *
     * @param resource the resource to connect with
     */
    public void addLinkedResource(ContentResource resource) {
        if ( !resource.getLinkedContentFieldValues().contains(this) ) {
            resource.getLinkedContentFieldValues().add(this);
        }
        if ( !getLinkedPages().contains(resource) ) {
            getLinkedPages().add(resource);
        }
    }

    /**
     * Removes a connection between this CFV and a given content resource
     *
     * @param resource the resource
     */
    public void removeLinkedResource(ContentResource resource) {
        resource.getLinkedContentFieldValues().remove(this);
        getLinkedResources().remove(resource);
    }

    /**
     * Returns the content for field with type <code>MULTILINE_TYPE</code> and <code>HTML_TYPE</code> 
     *
     * @return byte array of the content
     * @struts.form-field
     * @hibernate.property type="com.blandware.atleap.persistence.hibernate.util.BinaryBlobType"
     * @hibernate.column name="`value`" not-null="false"
     * length="${database.blob.size.max}"
     */
    public byte[] getValue() {
        return value;
    }

    /**
     * Sets the content for field with type <code>MULTILINE_TYPE</code> and <code>HTML_TYPE</code>
     *
     * @param value byte array of the content
     */
    public void setValue(byte[] value) {
        this.value = value;
    }

	public boolean equals(Object o) {
		if ( this == o ) {
			return true;
		}
		if ( !(o instanceof ContentFieldValue) ) {
			return false;
		}

		final ContentFieldValue contentFieldValue = (ContentFieldValue) o;

		if ( contentField != null ? !contentField.equals(contentFieldValue.contentField) : contentFieldValue.contentField != null ) {
			return false;
		}
		if ( contentLocale != null ? !contentLocale.equals(contentFieldValue.contentLocale) : contentFieldValue.contentLocale != null ) {
			return false;
		}

		return true;
	}

	public int hashCode() {
		int result;
		result = (contentLocale != null ? contentLocale.hashCode() : 0);
		result = 29 * result + (contentField != null ? contentField.hashCode() : 0);
		return result;
	}

}
